//使用变量定义三种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
//1.写一个构造函数 搭建基本结构
class BasicPromise {
  //2.函数执行器 定义 resolve 和 reject方法
  constructor(executor) {
    //定义初始状态 初始化值
    this.state = PENDING
    this.value = undefined
    this.reason = undefined
    //如果.then里面是异步函数 需要先将代码存储起来然后等待 resolve 或者 reject 执行完毕拿到结果后再去执行
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
    //resolve方法
    const resolve = value => {
      //当触发resolve方法时 判断状态是否在pending 如果在 就需要改变状态至 FULFILLED
      if(this.state === PENDING) {
        this.state = FULFILLED
        this.value = value
        //因为是数组 所以需要去循环依次执行
        this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(onFulfilled => onFulfilled(value))
      }
    }

    //reject方法
    const reject = reason => {
      //当触发reject方法时 判断状态是否在pending 如果在 就需要改变状态至 REJECTED
      if(this.state === PENDING) {
        this.state = REJECTED
        this.reason = reason
        //因为是数组 所以需要去循环依次执行
        this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(onRejected => onRejected(reason))
      }
    }
    //错误的抛出
    try {
      executor(resolve,reject)
    } catch (error) {
      throw error
    }
  }


  //promise的.then方法 接收两个参数
  then(onFulfilled,onRejected) {
        //同步代码
        //根据状态来判断 要执行的函数 如果状态为FULFILLED 则执行onFulfilled函数 并传入对应的value
        //保证promise执行是异步
      if(this.state === FULFILLED) {
        typeof onFulfilled === 'function' && setTimeout(() => {
          onFulfilled(this.value)
        }, 0)
        //同步代码
        //根据状态来判断 要执行的函数 如果状态为REJECTED 则执行onRejected函数 并传入对应的reason
        //保证promise执行是异步
      }else if(this.state === REJECTED) {
        typeof onRejected === 'function' && setTimeout(() => {
           onRejected(this.reason)
        }, 0)
      }else {
        //异步代码
        //根据状态来判断 要执行的函数 如果状态为PENDING 则判断对应的resolve 或者 reject 并将代码存储起来
        //保证promise执行是异步
        if(typeof onFulfilled === 'function') {
          //要保证.then方法的多次调用 所以需要去使用数组依次存储
          this.onFulfilledCallbacks.push(value => setTimeout(()=> {
              onFulfilled(value)
          },0))
        }
        if(typeof onRejected === 'function') {
          //要保证.then方法的多次调用 所以需要去使用数组依次存储
          this.onRejectedCallbacks.push(reason => setTimeout(()=> {
            onRejected(reason)
          },0))
        }
      }
  }
}
